import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class Pull2RefreshHeader extends StatefulWidget {
  @override
  _Pull2RefreshHeaderState createState() => _Pull2RefreshHeaderState();
}

class _Pull2RefreshHeaderState extends State<Pull2RefreshHeader> {
  final double _refreshHeight = 160.h;

  @override
  Widget build(BuildContext context) {
    return CustomHeader(
      completeDuration: Duration(milliseconds: 1),
      height: _refreshHeight,
      builder: (BuildContext context, RefreshStatus mode) {
        Widget body;
        if (mode == RefreshStatus.idle) {
          body = StaticRefreshHeaderOrFooter(refreshHeight: _refreshHeight);
        } else if (mode == RefreshStatus.refreshing) {
          body = AnimateRefreshHeaderOrFooter(refreshHeight: _refreshHeight);
        } else if (mode == RefreshStatus.failed) {
          body = Text("refresh fail");
        } else if (mode == RefreshStatus.canRefresh) {
          body = StaticRefreshHeaderOrFooter(refreshHeight: _refreshHeight);
        } else {
          body = StaticRefreshHeaderOrFooter(refreshHeight: _refreshHeight);
        }
        return Container(
            color: Colors.grey, height: ScreenUtil.screenHeight, alignment: Alignment.bottomCenter, child: body);
      },
    );
  }
}

class StaticRefreshHeaderOrFooter extends StatelessWidget {
  final refreshHeight;

  const StaticRefreshHeaderOrFooter({Key key, this.refreshHeight}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      height: refreshHeight,
      width: double.infinity,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Transform.translate(
            offset: Offset(0, 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.red,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          ClipOval(
            child: Container(
              height: 15.w,
              width: 15.w,
              color: Colors.blue,
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          ClipOval(
            child: Container(
              height: 15.w,
              width: 15.w,
              color: Colors.green,
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          ClipOval(
            child: Container(
              height: 15.w,
              width: 15.w,
              color: Colors.yellow,
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          ClipOval(
            child: Container(
              height: 15.w,
              width: 15.w,
              color: Colors.orange,
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
        ],
      ),
    );
  }
}

class AnimateRefreshHeaderOrFooter extends StatefulWidget {
  final double refreshHeight;

  const AnimateRefreshHeaderOrFooter({Key key, this.refreshHeight}) : super(key: key);

  @override
  _AnimateRefreshHeaderOrFooterState createState() => _AnimateRefreshHeaderOrFooterState();
}

class _AnimateRefreshHeaderOrFooterState extends State<AnimateRefreshHeaderOrFooter> with TickerProviderStateMixin {
  Animation<double> _doubleAnimation;
  AnimationController _animationController;
  Animation<double> _doubleAnimation2;
  AnimationController _animationController2;
  Animation<double> _doubleAnimation3;
  AnimationController _animationController3;
  Animation<double> _doubleAnimation4;
  AnimationController _animationController4;
  Animation<double> _doubleAnimation5;
  AnimationController _animationController5;

  final Duration _beatDuration = Duration(milliseconds: 400);
  final int _internalMilliseconds = 200;
  final double _offsetHeight = -40.h;

  @override
  void initState() {
    super.initState();
    _initAnimation();

    _startDelayAnimation(_animationController, 0 * _internalMilliseconds);
    _startDelayAnimation(_animationController2, 1 * _internalMilliseconds);
    _startDelayAnimation(_animationController3, 2 * _internalMilliseconds);
    _startDelayAnimation(_animationController4, 3 * _internalMilliseconds);
    _startDelayAnimation(_animationController5, 4 * _internalMilliseconds);
  }

  _startDelayAnimation(AnimationController animationController, int milliseconds) async {
    await Future.delayed(Duration(milliseconds: milliseconds));
    if (mounted) {
      animationController.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      height: widget.refreshHeight,
      width: double.infinity,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Transform.translate(
            offset: Offset(0, _doubleAnimation.value ?? 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.red,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          Transform.translate(
            offset: Offset(0, _doubleAnimation2.value ?? 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.blue,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          Transform.translate(
            offset: Offset(0, _doubleAnimation3.value ?? 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.green,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          Transform.translate(
            offset: Offset(0, _doubleAnimation4.value ?? 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.yellow,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
          Transform.translate(
            offset: Offset(0, _doubleAnimation5.value ?? 0),
            child: ClipOval(
              child: Container(
                height: 15.w,
                width: 15.w,
                color: Colors.orange,
              ),
            ),
          ),
          SizedBox(
            width: 15.w,
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    _animationController2.dispose();
    _animationController3.dispose();
    _animationController4.dispose();
    _animationController5.dispose();
    super.dispose();
  }

  void _initAnimation() {
    _animationController = AnimationController(vsync: this, duration: _beatDuration);
    _doubleAnimation = Tween<double>(begin: 0.0, end: _offsetHeight).animate(_animationController)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) async {
        if (status == AnimationStatus.completed) {
          _animationController.reverse();
        }
        if (status == AnimationStatus.dismissed) {
          await Future.delayed(Duration(milliseconds: _internalMilliseconds*4));
          if(mounted) {
            _animationController.forward();
          }
        }
      });

    _animationController2 = AnimationController(vsync: this, duration: _beatDuration);
    _doubleAnimation2 = Tween<double>(begin: 0.0, end: _offsetHeight).animate(_animationController2)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) async {
        if (status == AnimationStatus.completed) {
          _animationController2.reverse();
        }
        if (status == AnimationStatus.dismissed) {
          await Future.delayed(Duration(milliseconds: _internalMilliseconds*4));
          if(mounted) {
            _animationController2.forward();
          }
        }
      });

    _animationController3 = AnimationController(vsync: this, duration: _beatDuration);
    _doubleAnimation3 = Tween<double>(begin: 0.0, end: _offsetHeight).animate(_animationController3)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) async {
        if (status == AnimationStatus.completed) {
          _animationController3.reverse();
        }
        if (status == AnimationStatus.dismissed) {
          await Future.delayed(Duration(milliseconds: _internalMilliseconds*4));
          if(mounted) {
            _animationController3.forward();
          }
        }
      });

    _animationController4 = AnimationController(vsync: this, duration: _beatDuration);
    _doubleAnimation4 = Tween<double>(begin: 0.0, end: _offsetHeight).animate(_animationController4)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) async {
        if (status == AnimationStatus.completed) {
          _animationController4.reverse();
        }
        if (status == AnimationStatus.dismissed) {
          await Future.delayed(Duration(milliseconds: _internalMilliseconds*4));
          if(mounted) {
            _animationController4.forward();
          }
        }
      });

    _animationController5 = AnimationController(vsync: this, duration: _beatDuration);
    _doubleAnimation5 = Tween<double>(begin: 0.0, end: _offsetHeight).animate(_animationController5)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) async {
        if (status == AnimationStatus.completed) {
          _animationController5.reverse();
        }
        if (status == AnimationStatus.dismissed) {
          await Future.delayed(Duration(milliseconds: _internalMilliseconds*4));
          if(mounted) {
            _animationController5.forward();
          }
        }
      });
  }
}
